package machine;

import generation.Declaration;
import generation.Ecriture;

import java.io.OutputStream;

public class MAPasm{
	
protected static OutputStream flux; 
private static int messageCourant = 0;
	
	
	public static void entete(String rose){
		flux=Ecriture.ouvrir(rose+".asm");
		Ecriture.ecrireStringln(flux,"; entete");
		Ecriture.ecrireStringln(flux,"extrn lirent:proc, ecrent:proc");
		Ecriture.ecrireStringln(flux,"extrn ecrbool:proc");
		Ecriture.ecrireStringln(flux,"extrn ecrch:proc, ligsuiv:proc");
		Ecriture.ecrireStringln(flux,"");
		Ecriture.ecrireStringln(flux,".model SMALL");
		Ecriture.ecrireStringln(flux,".586");
		Ecriture.ecrireStringln(flux,"");
		Ecriture.ecrireStringln(flux,".CODE");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void queue(){
		Ecriture.ecrireStringln(flux,"\t; queue");
		Ecriture.ecrireStringln(flux,"\tnop");
		Ecriture.ecrireStringln(flux,"\texitcode");
		Ecriture.ecrireStringln(flux,"\tend");
		Ecriture.fermer(flux);
	}

	public static void iadd() {
		Ecriture.ecrireStringln(flux,"\t; iadd");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tadd ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void isub() {
		Ecriture.ecrireStringln(flux,"\t; isub");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tsub ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void ior() {
		Ecriture.ecrireStringln(flux,"\t; ior");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tor ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void ineg() {
		Ecriture.ecrireStringln(flux,"\t; ineg");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tmov ax,0");
		Ecriture.ecrireStringln(flux,"\tsub ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void imul() {
		Ecriture.ecrireStringln(flux,"\t; imul");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\timul bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void idiv() {
		Ecriture.ecrireStringln(flux,"\t; idiv");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcwd");
		Ecriture.ecrireStringln(flux,"\tidiv bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void iinf() {
		Ecriture.ecrireStringln(flux,"\t; iinf");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tjge $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void iinfegal() {
		Ecriture.ecrireStringln(flux,"\t; iinfegal");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tjg $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void isup() {
		Ecriture.ecrireStringln(flux,"\t; isup");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tjle $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void isupegal() {
		Ecriture.ecrireStringln(flux,"\t; isupegal");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tjl $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void iegal() {
		Ecriture.ecrireStringln(flux,"\t; iegal");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tjne $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void idiff() {
		Ecriture.ecrireStringln(flux,"\t; idiff");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tcmp ax,bx");
		Ecriture.ecrireStringln(flux,"\tje $+6");
		Ecriture.ecrireStringln(flux,"\tpush -1");
		Ecriture.ecrireStringln(flux,"\tjmp $+4");
		Ecriture.ecrireStringln(flux,"\tpush 0");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void iconst(String const1) {
		Ecriture.ecrireStringln(flux,"\t; iconst " + const1);
		Ecriture.ecrireStringln(flux,"\tpush " + const1);
		Ecriture.ecrireStringln(flux,"");
	}
	
	public static void iload(int var1) {
		Ecriture.ecrireStringln(flux,"\t; iload "+var1);
		if( var1 < 0 ){
			Ecriture.ecrireStringln(flux,"\tpush word ptr [bp" + var1 + "]");
		}
		else{
			Ecriture.ecrireStringln(flux,"\tpush word ptr [bp+" + var1 + "]");
		}
		Ecriture.ecrireStringln(flux,"");
	}

	public static void iand() {
		Ecriture.ecrireStringln(flux,"\t; iand");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tand ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
		
	}
	
	public static void inot() {
		Ecriture.ecrireStringln(flux,"\t; inot");
		Ecriture.ecrireStringln(flux,"\tpop bx");
		Ecriture.ecrireStringln(flux,"\tpop ax");
		Ecriture.ecrireStringln(flux,"\tnot ax,bx");
		Ecriture.ecrireStringln(flux,"\tpush ax");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void ouvrePrinc() {
		Ecriture.ecrireStringln(flux,"\t; ouvrePrinc");
		Ecriture.ecrireStringln(flux,"debut:");
		Ecriture.ecrireStringln(flux,"\tSTARTUPCODE");
		Ecriture.ecrireStringln(flux,"");
		
	}

	public static void istore(int var1) {
		Ecriture.ecrireStringln(flux,"\t; istore" + var1);
		Ecriture.ecrireStringln(flux,"\tpop ax");
		if( var1 < 0 ){
			Ecriture.ecrireStringln(flux,"\tmov word ptr[bp" + var1 +"],ax");
		}
		else{
			Ecriture.ecrireStringln(flux,"\tmov word ptr[bp+" + var1 +"],ax");
		}
		Ecriture.ecrireStringln(flux,"");
	}

	public static void lireEnt(int offset) {
		Ecriture.ecrireStringln(flux,"\t; lireEnt " + offset);
		Ecriture.ecrireStringln(flux,"\tlea dx,[bp" + offset + "]");
		Ecriture.ecrireStringln(flux,"\tpush dx");
		Ecriture.ecrireStringln(flux,"\tcall lirent");
		Ecriture.ecrireStringln(flux,"");
	}

	public static void ecrireEnt() {
		Ecriture.ecrireStringln(flux,"\t; ecrireEnt");
		Ecriture.ecrireStringln(flux,"\tcall ecrent");
		Ecriture.ecrireStringln(flux,"");
		
	}

	public static void ecrireChaine(String chaineLue) {
		Ecriture.ecrireStringln(flux,"\t; ecrireChaine " + chaineLue);
		Ecriture.ecrireStringln(flux,".DATA");
		Ecriture.ecrireStringln(flux,"\tmess" + messageCourant + " db " + chaineLue.substring(0,chaineLue.length()-1) +"$" + chaineLue.substring(0, 1) );
		Ecriture.ecrireStringln(flux,".CODE");
		Ecriture.ecrireStringln(flux,"\tlea dx,mess"+messageCourant);
		Ecriture.ecrireStringln(flux,"\tpush dx");
		Ecriture.ecrireStringln(flux,"\tcall ecrch");
		Ecriture.ecrireStringln(flux,"");
		messageCourant++;
		
	}

	public static void si(Integer peek) {
		Ecriture.ecrireStringln(flux, "\t; iffaux sinon"+peek);
		Ecriture.ecrireStringln(flux, "\tpop ax");
		Ecriture.ecrireStringln(flux, "\tcmp ax,0");
		Ecriture.ecrireStringln(flux, "\tje sinon"+peek);
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void sinon(Integer peek) {
		Ecriture.ecrireStringln(flux, "\t; sinon"+peek);
		Ecriture.ecrireStringln(flux, "\tjmp fsi"+peek);
		Ecriture.ecrireStringln(flux, "sinon"+peek+":");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void fsi(Integer pop) {
		Ecriture.ecrireStringln(flux, "\t; fsi"+pop);
		Ecriture.ecrireStringln(flux, "fsi"+pop+":");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void tantque(Integer peek) {
		Ecriture.ecrireStringln(flux, "\t; tant que "+peek);
		Ecriture.ecrireStringln(flux, "faire"+peek+":");
		
	}

	public static void faire(Integer peek) {
		Ecriture.ecrireStringln(flux, "\t; faire "+peek);
		Ecriture.ecrireStringln(flux, "\tmov ax,-1");
		Ecriture.ecrireStringln(flux, "\tpop bx");
		Ecriture.ecrireStringln(flux, "\tcmp ax,bx");
		Ecriture.ecrireStringln(flux, "\tjne fait"+peek);
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void fait(Integer pop) {
		Ecriture.ecrireStringln(flux, "\t; goto "+pop);
		Ecriture.ecrireStringln(flux, "\tjmp faire"+pop);
		Ecriture.ecrireStringln(flux, "");
		Ecriture.ecrireStringln(flux, "fait"+pop+":");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void alaligne() {
		Ecriture.ecrireStringln(flux, "\t; alaligne");
		Ecriture.ecrireStringln(flux, "\tcall ligsuiv");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void fermeBloc(int tailleVar) {
		Ecriture.ecrireStringln(flux, "\t; fermebloc");
		Ecriture.ecrireStringln(flux, "\tleave");
		Ecriture.ecrireStringln(flux, "\tret "+tailleVar);
		Ecriture.ecrireStringln(flux, "");

	}

	public static void ouvreBloc(int tailleVar,String nom) {
		Ecriture.ecrireStringln(flux, nom+":");
		Ecriture.ecrireStringln(flux, "\t; ouvrebloc");
		Ecriture.ecrireStringln(flux, "\tenter "+tailleVar+",0");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void ireturn(int offset) {
		Ecriture.ecrireStringln(flux, "\t; ireturn");
		Ecriture.ecrireStringln(flux, "\tpop ax");
		Ecriture.ecrireStringln(flux, "\tmov [bp+"+offset+"],ax");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void reserveRetour() {
		Ecriture.ecrireStringln(flux, "\t; reserveretour");
		Ecriture.ecrireStringln(flux, "\tsub sp,2");
		Ecriture.ecrireStringln(flux, "");
		
	}

	public static void call(String nom) {
		Ecriture.ecrireStringln(flux, "\t; call");
		Ecriture.ecrireStringln(flux, "\tcall "+nom);
		Ecriture.ecrireStringln(flux, "");
		
	}

}
